package com.nine.pesys.util.common;

import java.util.Arrays;

/**生成随机的数据，后面根据这些数据生成验证码
 * Created by etund on 2014/10/23.
 */
public class CreateCode {

    /**
     *      设计验证码的难度级别 SIMPLE为简单：包含数字 MEDIUM为中等难度，包含数字和小写字母     HARD为最高难度，包含数字和大小写字母
     */
    public enum SecurityCodeLevel{
        SIMPLE,MEDIUM,HARD
    }

    /**
     * 设置默认的验证码属性，默认验证码难度为MEDIUM
     * @return
     */
    public static String getSecurityCode(){
        return getSecurityCode(4, SecurityCodeLevel.MEDIUM, false);
    }


    public static String getSecurityCode(int length, SecurityCodeLevel level, boolean isCanRepeat) {
        /**
         * 声明验证码位数
         */
        int len = length;

        /**
         * 定义一个字符数组，出去易混淆的字符（o 跟 O, ）
         */
        char[] codes={'1','2','3','4','5','6','7','8','9',
                                'a','b','c','d','e','f','g','h','i',
                                'j','k','m','n','p','q','r','s','t',
                                'u','v','w','x','y','z','A','B','C',
                                'D','E','F','G','H','I','J','K','L',
                                'M','N','P','Q','R','S','T','U','V',
                                'W','X','Y','Z'};

        /**
         * copyOfRange(char[] original, int from, int to)将指定数组的指定范围复制到一个新数组。
         * 得到一个新的codes
         */

        if(level == SecurityCodeLevel.SIMPLE){
            codes = Arrays.copyOfRange(codes,0,9);
        }else if (level == SecurityCodeLevel.MEDIUM){
            codes = Arrays.copyOfRange(codes,0,33);
        }
        int codesLength = codes.length;

        /**
         * 你索要截取的数据比你所要截取的对象的长度要长，并且不能有字符重复，说明你的数据不能够提供给你用
        *  format(String format, Object... args) 使用指定的格式字符串和参数返回一个格式化字符串。
         */
        if(len>codesLength&isCanRepeat==false){
            throw new RuntimeException(String.format("调用SecurityCode.getSecurityCode(%1$s,%2$s,%3$s)出现异常，" +
                                                           "当isCanRepeat为%3$s时，传入参数%1$s不能大于%4$s",
                                                           len,level,isCanRepeat,codesLength));
        }

        /**
         * 存放截取出来的字符
         */
        char[] result = new char[len];

        /**
         * 判断是否可以重复，从而生成带有重复或者不重复字符的验证码
         */
        if(isCanRepeat){
            for(int i = 0 ; i<result.length;i++) {
                int r = (int) (Math.random() * codesLength);
                result[i] = codes[r];
            }
        }else {
            for (int i = 0 ; i < result.length ;i++){
                int r = (int)(Math.random()*codesLength);
                result[i] = codes[r];
                /**
                 * if	code[r] = code[n-1]
                 result[i] = code[r]
                 code[r] = code[n-1]
                 n--
                 code[r]不见 可以保持不重复
                 if	code[r] != code[n-1]
                 code[r] = code[n-1]
                 code[r] 变为 最后一个元素
                 code[n-1] 消失
                 综上，这个算法可以确保不重复
                 */
                codes[r] = codes[codesLength-1];
                codesLength--;
            }
        }
        /**
         * valueOf(char[] data)     返回 char 数组参数的字符串表示形式。
         */
        return String.valueOf(result);
    }
}
